﻿/**
 * GoText Palm: A program that allows to send text messages over the internet.
 *  Copyright (C) 2008 Nicola 'Gawaine' Racco
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Net;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data.SqlTypes;
using GoTextPalm.Core.Persistence;
using System.IO;
using System.Drawing;
using GoTextPalm.Core.Localization;
using GoTextPalm.Core.Localization.Reducer;
using GoTextPalm.Core.Data;

namespace GoTextPalm.Core
{
    public class ServiceLogic
    {
        public static Service CreateService(string name, string url)
        {
            if (DBService.ExistsService(name))
            {
                String str = "A service with the same name already exists";
                try
                {
                    str = ResourceManager.Instance.GetString("ServiceLogic_srvexists");
                }
                catch { }
                throw new Exception(str);
            }
            Service s = new Service();
            s.Name = name;
            s.Url = url;
            LoadConfig(ref s);
            return s;
        }

        public static void SaveMessage(int IDService, ref Message mex)
        {
            DBMessage.AddMessage(IDService, ref mex);
        }

        public static void SetSavingLastMessageEnabled(bool value)
        {
            DBConfig.set("lastMessageSaving", Convert.ToString(value));
        }

        public static bool GetSavingLastMessageEnabled()
        {
            String v = DBConfig.get("lastMessageSaving");
            if (v == null || v == String.Empty)
                return false;
            return Convert.ToBoolean(v);
        }

        public static int GetSavingMessagesEnabled() 
        {
            String v = DBConfig.get("messageSaving");
            if (v == null || v == String.Empty)
                return -1;
            return Convert.ToInt32(v);
        }

        public static int GetSavingPolicy()
        {
            String v = DBConfig.get("savingPolicy");
            if (v == null || v == String.Empty)
                return 1;
            return Convert.ToInt32(v);
        }

        public static void SetSavingMessagesEnabled(int savingMessages)
        {
            DBConfig.set("messageSaving", Convert.ToString(savingMessages));
        }

        public static void SetSavingPolicy(int savingPolicy)
        {
            DBConfig.set("savingPolicy", Convert.ToString(savingPolicy));
        }

        public static void PersistService(ref Service s)
        {
            DBService.PersistService(ref s);
        }

        private static void LoadConfig(ref Service s)
        {
            try
            {
                LinkedList<char> xc = new LinkedList<char>();
                LinkedList<string> sc = new LinkedList<string>();
                LinkedList<char> cm = new LinkedList<char>();
                LinkedList<int> cf = new LinkedList<int>();

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(s.Url + "?" + Constants.PARAM_CONFIG + "&" + Constants.PARAM_SPV);
                request.KeepAlive = false;
                request.Method = "GET";
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                XmlReader reader = XmlReader.Create(response.GetResponseStream());
                XmlDocument doc = new XmlDocument();
                XmlNode configNode = doc.ReadNode(reader);
                //+Retrocompatibilita' con servizi datati
                if (configNode.Name == "res")
                    configNode = configNode.FirstChild;
                //-
                foreach (XmlNode node in configNode.ChildNodes)
                    switch (node.Name)
                    {
                        case "t": s.Welcome = node.InnerText; break;
                        case "nu":
                            int i = Convert.ToInt32(node.InnerText);
                            s.NeedsUsername = i == 1;
                            break;
                        case "np":
                            int np = Convert.ToInt32(node.InnerText);
                            s.NeedsPassword = np == 1;
                            break;
                        case "nn":
                            int nn = Convert.ToInt32(node.InnerText);
                            s.NeedsNickname = (nn == 1);
                            break;
                        case "mr": s.MaxRecipiens = Convert.ToInt32(node.InnerText); break;
                        case "mc": s.MaxChars = Convert.ToInt32(node.InnerText); break;
                        case "in":
                            s.Type = (Service.ServiceType)Convert.ToInt32(node.InnerText);
                            break;
                        case "mm":
                            s.MaxMessages = Convert.ToInt32(node.InnerText);
                            s.MMMode = Service.MaxMessagesMode.DAILY;
                            break;
                        case "mmm":
                            s.MaxMessages = Convert.ToInt32(node.InnerText);
                            s.MMMode = Service.MaxMessagesMode.MONTHLY;
                            break;
                        case "xc":
                            string[] xcv = node.InnerText.Split('|');
                            foreach (string v in xcv)
                                xc.AddLast(v.ToCharArray()[0]);
                            break;
                        case "sc":
                            string[] scv = node.InnerText.Split('|');
                            foreach (string v in scv)
                                sc.AddLast(v);
                            break;
                        case "cm":
                            string[] cmv = node.InnerText.Split('|');
                            foreach (string v in cmv)
                                cm.AddLast(v.ToCharArray()[0]);
                            break;
                        case "cf":
                            string[] cfv = node.InnerText.Split('|');
                            foreach (string v in cfv)
                                cf.AddLast(Convert.ToInt32(v));
                            break;
                    }
                reader.Close();
                response.Close();
                if (xc.Count > 0 && xc.Count == sc.Count)
                {
                    LinkedList<char>.Enumerator en = xc.GetEnumerator();
                    LinkedList<string>.Enumerator en2 = sc.GetEnumerator();
                    while (en.MoveNext() && en2.MoveNext())
                        s.CharsToReplace.Add(en.Current, en2.Current);
                }
                else if (xc.Count != sc.Count)
                {
                    String str = "The Service response is incorrect";
                    try
                    {
                        str = ResourceManager.Instance.GetString("ServiceLogic_badsrvres");
                    }
                    catch { }
                    throw new Exception(str);
                }
                if (cm.Count > 0 && cm.Count == cf.Count)
                {
                    LinkedList<char>.Enumerator en = cm.GetEnumerator();
                    LinkedList<int>.Enumerator en2 = cf.GetEnumerator();
                    while (en.MoveNext() && en2.MoveNext())
                        s.CharsToRecount.Add(en.Current, en2.Current);
                }
                else if (cm.Count != cf.Count)
                {
                    String str = "The Service response is incorrect. Maybe the service is incompatible";
                    try
                    {
                        str = ResourceManager.Instance.GetString("ServiceLogic_badsrvres");
                    }
                    catch { }
                    throw new Exception(str);
                }
            }
            catch (DBException e)
            {
                throw e;
            }
            catch (XmlException e)
            {
                String str = "The Service response is incorrect. Maybe the service is incompatible";
                try
                {
                    str = ResourceManager.Instance.GetString("ServiceLogic_badsrvres");
                }
                catch { }
                throw new Exception(str);
            }
            catch (Exception e)
            {
                String str = "Cannot connect to the service. Maybe the internet connection is absent.";
                try
                {
                    str = ResourceManager.Instance.GetString("ServiceLogic_loadex1");
                }
                catch { }
                throw new ConnectException(str);
            }
        }

        public static void SaveServiceConfig(Service s, String username, String nickname, String password)
        {
            if (s.Config == null)
                s.Config = new Service.ServiceConfig();
            s.Config.Username = s.NeedsUsername ? new SqlString(username) : SqlString.Null;
            s.Config.Password = s.NeedsPassword ? new SqlString(password) : SqlString.Null;
            s.Config.Nickname = s.NeedsNickname ? new SqlString(nickname) : SqlString.Null;
            DBService.PersistServiceConfig(s);
        }

        public static void DeleteService(Service s)
        {
            DBService.DeleteService(s);
        }

        public static void SetLanguage(Language l)
        {
            ResourceManager.Instance.Culture = l.CultureInfo;
            Converter.Instance.cmd = l.Converter;
            Reducer.Instance.cmd = l.Reducer;
            DBConfig.set("lang", l.LangCode);
        }

        internal static void SaveLastMessage(Service service, ref Message message)
        {
            DBMessage.SetLastMessageSent(service.Id.Value, ref message);
        }
    }
}
